/******************************************************************************* * Copyright (c) 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation ******************************************************************************/ package org.eclipse.ui.internal.e4.migration; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.annotation.PostConstruct; import javax.inject.Inject; import org.eclipse.e4.ui.model.application.ui.MElementContainer; import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.e4.ui.model.application.ui.SideValue; import org.eclipse.e4.ui.model.application.ui.advanced.MArea; import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective; import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack; import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer; import org.eclipse.e4.ui.model.application.ui.basic.MPartStack; import org.eclipse.e4.ui.model.application.ui.basic.MStackElement; import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar; import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.e4.ui.model.application.ui.menu.MToolControl; import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuFactoryImpl; import org.eclipse.e4.ui.workbench.IPresentationEngine; import org.eclipse.e4.ui.workbench.addons.minmax.TrimStack; import org.eclipse.e4.ui.workbench.modeling.EModelService; import org.eclipse.e4.ui.workbench.modeling.EPartService; import org.eclipse.e4.ui.workbench.renderers.swt.TrimBarLayout; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.internal.IPreferenceConstants; import org.eclipse.ui.internal.Workbench; import org.eclipse.ui.internal.WorkbenchWindow; import org.eclipse.ui.internal.e4.compatibility.CompatibilityEditor; import org.eclipse.ui.internal.e4.compatibility.CompatibilityPart; import org.eclipse.ui.internal.e4.compatibility.ModeledPageLayout; import org.eclipse.ui.internal.e4.compatibility.ModeledPageLayoutUtils; import org.eclipse.ui.internal.e4.migration.WindowReader.EditorReader; import org.eclipse.ui.internal.e4.migration.WindowReader.ViewReader; import org.eclipse.ui.internal.registry.StickyViewDescriptor; import org.eclipse.ui.internal.registry.ViewRegistry; public class WindowBuilder { private MWindow window; private List<MUIElement> sharedElements; private MPartSashContainer mainSash; @Inject private WindowReader windowReader; @Inject private EModelService modelService; @Inject private IModelBuilderFactory factory; private ModeledPageLayoutUtils layoutUtils; private MArea editorArea; private List<MPerspective> perspectives; public static String PERSPECTIVES = "perspectives"; //$NON-NLS-1$ @PostConstruct private void postConstruct() { layoutUtils = new ModeledPageLayoutUtils(modelService); } MWindow createWindow() { create(); populate(); return window; } boolean isSelected() { return windowReader.isSelected(); } boolean isWelcomePageOpen() { return windowReader.isWelcomePageOpen(); } private void create() { window = modelService.createModelElement(MTrimmedWindow.class); Rectangle bounds = windowReader.getBounds(); window.setX(bounds.x); window.setY(bounds.y); window.setWidth(bounds.width); window.setHeight(bounds.height); window.getTags().add("topLevel"); //$NON-NLS-1$ String coolbarVisible = Boolean.TRUE.toString(); if (!windowReader.isCoolbarVisible() && !isWelcomePageOpen()) { coolbarVisible = Boolean.FALSE.toString(); } window.getPersistedState().put(IPreferenceConstants.COOLBAR_VISIBLE, coolbarVisible); window.getPersistedState().put(IPreferenceConstants.PERSPECTIVEBAR_VISIBLE, coolbarVisible); // necessary to force correct order of window initial // rendering when there is no perspective if (windowReader.isStatusBarVisible()) { MTrimBar statusBar = modelService.getTrim((MTrimmedWindow) window, SideValue.BOTTOM); if (windowReader.hasStatusLine()) { MToolControl statusLine = modelService.createModelElement(MToolControl.class); statusLine.setElementId(WorkbenchWindow.STATUS_LINE_ID); statusLine.setContributionURI(WorkbenchWindow.TRIM_CONTRIBUTION_URI); statusLine.getTags().add(TrimBarLayout.SPACER); statusBar.getChildren().add(statusLine); } } List<String> tags = window.getTags(); if (windowReader.isMinimized()) { tags.add(IPresentationEngine.WINDOW_MINIMIZED_TAG); } else if (windowReader.isMaximized()) { tags.add(IPresentationEngine.WINDOW_MAXIMIZED_TAG); } sharedElements = window.getSharedElements(); } private void populate() { addEditorArea(); addEditors(); addViews(); perspectives = new ArrayList<>(); mainSash = modelService.createModelElement(MPartSashContainer.class); mainSash.setHorizontal(true); MPerspectiveStack perspectiveStack = createPerspectiveStack(); mainSash.getChildren().add(perspectiveStack); mainSash.setSelectedElement(perspectiveStack); window.getChildren().add(mainSash); window.setSelectedElement(mainSash); for (PerspectiveReader perspReader : windowReader.getPerspectiveReaders()) { PerspectiveBuilder builder = factory.createPerspectiveBuilder(perspReader); MPerspective perspective = builder.createPerspective(windowReader.getDefaultFastViewSide()); perspectiveStack.getChildren().add(perspective); MPlaceholder eaPlaceholder = builder.getEditorAreaPlaceholder(); if (eaPlaceholder != null) { eaPlaceholder.setRef(editorArea); } for (MPlaceholder viewPlaceholder : builder.getPlaceholders()) { String id = viewPlaceholder.getElementId(); if (id != null) { viewPlaceholder.setRef(getSharedView(id)); } } perspectives.add(perspective); } String activePerspectiveId = windowReader.getActivePerspectiveId(); if (activePerspectiveId != null) { for (MPerspective persp : perspectiveStack.getChildren()) { String id = persp.getElementId(); String originalId = (String) persp.getTransientData().get( PerspectiveBuilder.ORIGINAL_ID); if (originalId != null) { id = originalId; } if (activePerspectiveId.equals(id)) { perspectiveStack.setSelectedElement(persp); createTrimBars(persp); break; } } } addStickyFolder(); window.getTransientData().put(PERSPECTIVES, perspectives); } private void createTrimBars(MPerspective perspective) { // Find any minimized stacks and show their trim List<MUIElement> minimizedElements = modelService.findElements(perspective, null, MUIElement.class, Arrays.asList(IPresentationEngine.MINIMIZED)); for (MUIElement element : minimizedElements) { createTrim(element, perspective); } } private int getBarIndex(MUIElement element, String trimStr) { if (trimStr == null) return -1; String[] stacks = trimStr.split("#"); //$NON-NLS-1$ for (String stackInfo : stacks) { String[] vals = stackInfo.split(" "); //$NON-NLS-1$ if (vals[0].equals(element.getElementId())) { return Integer.parseInt(vals[1]); } } return -1; } private int getIndex(MUIElement element, String trimStr) { if (trimStr == null) return -1; String[] stacks = trimStr.split("#"); //$NON-NLS-1$ for (String stackInfo : stacks) { String[] vals = stackInfo.split(" "); //$NON-NLS-1$ if (vals[0].equals(element.getElementId())) { return Integer.parseInt(vals[2]); } } return -1; } private void createTrim(MUIElement element, MPerspective perspective) { if (!(window instanceof MTrimmedWindow)) { return; } String trimStr = perspective.getPersistedState().get("trims"); //$NON-NLS-1$ MTrimmedWindow win = (MTrimmedWindow) window; // Is there already a TrimControl there ? String trimId = element.getElementId() + getMinimizedElementSuffix(perspective); MToolControl trimStack = (MToolControl) modelService.find(trimId, window); if (trimStack == null) { trimStack = MenuFactoryImpl.eINSTANCE.createToolControl(); trimStack.setElementId(trimId); trimStack.setContributionURI(TrimStack.CONTRIBUTION_URI); trimStack.getTags().add("TrimStack"); //$NON-NLS-1$ // Check if we have a cached location MTrimBar bar = getBarForElement(element, win, trimStr); int index = getIndex(element, trimStr); if (index == -1 || index >= bar.getChildren().size()) bar.getChildren().add(trimStack); else bar.getChildren().add(index, trimStack); bar.setVisible(true); } else { // get the parent trim bar, see bug 320756 MUIElement parent = trimStack.getParent(); parent.setVisible(true); trimStack.setToBeRendered(true); } } private String getMinimizedElementSuffix(MPerspective perspective) { String id = "(minimized)"; //$NON-NLS-1$ if (perspective != null) { id = '(' + perspective.getElementId() + ')'; } return id; } private MTrimBar getBarForElement(MUIElement element, MTrimmedWindow window, String trimStr) { SideValue side = SideValue.get(getBarIndex(element, trimStr)); if (side == null) { side = SideValue.BOTTOM; } MTrimBar bar = modelService.getTrim(window, side); return bar; } private void addEditors() { Map<MPartStack, InfoReader> stackToReader = new HashMap<>(); // add stacks to shared area List<InfoReader> stackReaders = windowReader.getEditorStacks(); if (stackReaders.isEmpty()) { // create default stack MPartStack editorStack = modelService.createModelElement(MPartStack.class); editorStack.getTags().add(ModeledPageLayout.EDITOR_STACK_TAG); editorArea.getChildren().add(editorStack); } for (InfoReader stackReader : stackReaders) { stackToReader.put(addEditorStack(stackReader), stackReader); } editorArea.setSelectedElement(editorArea.getChildren().get(0)); for (EditorReader editorReader : windowReader.getEditors()) { MPart editor = modelService.createModelElement(MPart.class); editor.setElementId(CompatibilityEditor.MODEL_ELEMENT_ID); editor.setContributionURI(CompatibilityPart.COMPATIBILITY_EDITOR_URI); editor.setLabel(editorReader.getLabel()); editor.getPersistedState().put(Workbench.MEMENTO_KEY, new MementoSerializer(editorReader.getMemento()).serialize()); List<String> tags = editor.getTags(); tags.add(Workbench.EDITOR_TAG); tags.add(EPartService.REMOVE_ON_HIDE_TAG); tags.add(editorReader.getType()); MPartStack stack = (MPartStack) modelService.find(editorReader.getStackId(), editorArea); stack.getChildren().add(editor); if (editorReader.isSelected()) { stack.setSelectedElement(editor); } } // restore order of editors in stacks for (Entry<MPartStack, InfoReader> entry : stackToReader.entrySet()) { MPartStack editorStack = entry.getKey(); if (editorStack.getChildren().size() < 2) { continue; } InfoReader stackReader = entry.getValue(); if (stackReader == null) { continue; } int[] partOrder = stackReader.getPartOrder(); List<MStackElement> stackChildren = editorStack.getChildren(); List<MStackElement> originalOrder = new ArrayList<>(stackChildren); MStackElement selectedElement = editorStack.getSelectedElement(); stackChildren.clear(); for (int element : partOrder) { stackChildren.add(originalOrder.get(element)); } if (selectedElement != null) { editorStack.setSelectedElement(selectedElement); } } } private MPartStack addEditorStack(InfoReader info) { MPartStack stack = layoutUtils.createStack(info.getId(), true); if (info.isRelativelyPositioned()) { MUIElement refElement = modelService.find(info.getRelative(), editorArea); MElementContainer<?> parent = refElement.getParent(); if (parent instanceof MPartStack) { refElement = parent; } layoutUtils.insert(stack, refElement, layoutUtils.plRelToSwt(info.getRelationship()), info.getRatio()); } else { editorArea.getChildren().add(stack); } return stack; } private void addViews() { for (ViewReader viewReader : windowReader.getViews()) { sharedElements.add(createView(viewReader)); } } private MPart createView(ViewReader viewReader) { MPart view = modelService.createModelElement(MPart.class); view.setElementId(viewReader.getId()); view.setContributionURI(CompatibilityPart.COMPATIBILITY_VIEW_URI); view.setLabel(viewReader.getLabel()); view.getTags().add(ViewRegistry.VIEW_TAG); view.getPersistedState().put(Workbench.MEMENTO_KEY, new MementoSerializer(viewReader.getViewState()).serialize()); return view; } private void addEditorArea() { editorArea = modelService.createModelElement(MArea.class); sharedElements.add(editorArea); editorArea.setElementId(IPageLayout.ID_EDITOR_AREA); } private MPerspectiveStack createPerspectiveStack() { MPerspectiveStack perspStack = modelService .createModelElement(MPerspectiveStack.class); perspStack.setElementId("PerspectiveStack"); //$NON-NLS-1$ return perspStack; } private void addStickyFolder() { MPartStack stickyFolder = modelService.createModelElement(MPartStack.class); stickyFolder.setElementId(StickyViewDescriptor.STICKY_FOLDER_RIGHT); stickyFolder.setContainerData("2500"); //$NON-NLS-1$ stickyFolder.setToBeRendered(false); mainSash.getChildren().add(stickyFolder); } private MPart getSharedView(String id) { MPart part = null; for (MUIElement element : sharedElements) { if (id.equals(element.getElementId()) && element instanceof MPart) { part = (MPart) element; break; } } /* * if (part == null) { part = * modelService.createModelElement(MPart.class); part.setElementId(id); * part.setContributionURI(CompatibilityPart.COMPATIBILITY_VIEW_URI); * part.getTags().add(ViewRegistry.VIEW_TAG); sharedElements.add(part); * } */ return part; } }